#include "HttpServer.h"

HttpServer::HttpServer(QObject *parent)
{
    QSettings settings("http.ini",QSettings::IniFormat);
    new QTcpServer(parent);
    listen(QHostAddress::Any,settings.value("PORT").toInt());

    connect(this,SIGNAL(newConnection()),this,SLOT(newConnection()));
}

void HttpServer::newConnection()
{
    QTcpSocket *newGuy = nextPendingConnection();
    connect(newGuy,SIGNAL(readyRead()),this,SLOT(readyRead()));
    connect(newGuy,SIGNAL(disconnected()),this,SLOT(disconnected()));
    emit message("New guy connected, address is "+newGuy->peerAddress().toString()+"\n");
}

void HttpServer::readyRead()
{
    QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
    if (socket == 0)
        return;
    QString data = socket->readAll();
    emit message(data);
    respond(data,socket);
}

void HttpServer::disconnected()
{
    QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
    if (socket == 0)
        return;
    emit message("Client "+socket->peerAddress().toString()+" disconnected\n");
    socket->deleteLater();
}

void HttpServer::respond(const QString &data, QTcpSocket *socket)
{
    QSettings settings("http.ini",QSettings::IniFormat);
    QString root = settings.value("ROOT").toString();
    QString path;
    if(data.startsWith("GET"))
    {
        QString page,dir;
        QRegExp ex("GET (\\S*) HTTP/1.1");
        int pos = ex.indexIn(data.split('\n').at(0));
        if (pos > -1)
        {
            page = ex.cap(1);
            if(page == "/")
            {
                page = "/index.tdl";
            }
        }
        ex.setPattern("Host: (\\S*)");
        pos = ex.indexIn(data.split('\n').at(1));
        if (pos > -1)
        {
            dir = ex.cap(1);
        }
        else
        {
            int i = 2;
            while(i < data.split('\n').count())
            {
                pos = ex.indexIn(data.split('\n').at(i));
                if (pos > -1)
                {
                    dir = ex.cap(1);
                    break;
                }
                i++;
            }
        }
        path = root+dir+page;
        QFile pageFile(path);
        QString type;
        QFileInfo info(pageFile);
        if(info.suffix() == "html" || info.suffix() == "htm" || info.suffix() == "tdl")
        {
            type = "text/html";
        }
        else if(info.suffix() == "jpg" || info.suffix() == "jpeg")
        {
            type = "image/jpeg";
        }
        else if(info.suffix() == "gif")
        {
            type = "image/gif";
        }
        else if(info.suffix() == "png")
        {
            type = "image/png";
        }
        else if(info.suffix() == "css")
        {
            type = "text/css";
        }
        else if(info.suffix() == "js")
        {
            type = "text/javascript";
        }

        if (!pageFile.open(QIODevice::ReadOnly))
        {
            QDir dir(path);
            dir.setFilter(QDir::AllEntries);
            if(!dir.exists())
            {
                QFile errorDoc(settings.value("404DOC").toString());
                if(!errorDoc.open(QIODevice::ReadOnly))
                {
                    emit message("Cannot open 404 file "+errorDoc.fileName());
                }
                QByteArray data = errorDoc.readAll();
                socket->write("HTTP/1.1 404 ERROR\r\n\r\n"+data);
                emit message("HTTP/1.1 404 ERROR\n");
                socket->close();
            }
            else
            {
                QStringList filters;
                filters << "*";
                QStringList all = dir.entryList(filters);
                QString data = "<html><head><title>Directory listing</title></head><body><p><h1>Directory Listing</h1>";
                for(int i = 0; i < all.count(); i++)
                {
                    data+="<a href='"+all.at(i)+"'>"+all.at(i)+"</a></br>";
                }
                data+="</p></body></html>";
                socket->write("HTTP/1.1 200 OK\r\n\r\n"+data.toLatin1());
                emit message("HTTP/1.1 200 OK\r\nServer: TDL/0.18\r\n");
            }
        }
        else
        {
            socket->write(QByteArray("HTTP/1.1 200 OK\r\nServer: TDL/0.18\r\nContent-Type: "+type.toLatin1()+"\r\n\r\n"));
            emit message("HTTP/1.1 200 OK\r\nServer: TDL/0.18\r\nContent-Type: "+type+"\r\n\r\n");
        }
        QByteArray data = pageFile.readAll();
        if(info.suffix() == "tdl")
        {
            TDL *tdl = new TDL(QString(data));
            data = tdl->parse().toLatin1();
            emit message("Parsing...\n");
        }
        if(socket->write(data) != data.size())
        {
            emit message("Not all bytes were written\n");
        }
        socket->close();
    }
    else if(data.startsWith("HEAD"))
    {
        QString page,dir;
        QRegExp ex("HEAD (\\S*) HTTP/1.1");
        int pos = ex.indexIn(data.split('\n').at(0));
        if (pos > -1)
        {
            page = ex.cap(1);
            if(page == "/")
            {
                page = "/index.html";
            }
        }
        ex.setPattern("Host: (\\S*)");
        pos = ex.indexIn(data.split('\n').at(1));
        if (pos > -1)
        {
            dir = ex.cap(1);
        }
        else
        {
            int i = 2;
            while(i < data.split('\n').count())
            {
                pos = ex.indexIn(data.split('\n').at(i));
                if (pos > -1)
                {
                    dir = ex.cap(1);
                    break;
                }
                i++;
            }
        }
        path = root+dir+page;
        QFile pageFile(path);
        QString type;
        QFileInfo info(pageFile);
        if(info.suffix() == "html" || info.suffix() == "htm")
        {
            type = "text/html";
        }
        else if(info.suffix() == "jpg" || info.suffix() == "jpeg")
        {
            type = "image/jpeg";
        }
        else if(info.suffix() == "gif")
        {
            type = "image/gif";
        }
        else if(info.suffix() == "png")
        {
            type = "image/png";
        }
        else if(info.suffix() == "css")
        {
            type = "text/css";
        }
        else if(info.suffix() == "js")
        {
            type = "text/javascript";
        }

        if (!pageFile.open(QIODevice::ReadOnly))
        {
            QDir dir(path);
            dir.setFilter(QDir::AllEntries);
            if(!dir.exists())
            {
                QFile errorDoc(settings.value("404DOC").toString());
                if(!errorDoc.open(QIODevice::ReadOnly))
                {
                    emit message("Cannot open 404 file "+errorDoc.fileName());
                }
                QByteArray data = errorDoc.readAll();
                socket->write("HTTP/1.1 404 ERROR\r\n\r\n");
                emit message("HTTP/1.1 404 ERROR\n");
                socket->close();
            }
        }
        else
        {
            socket->write(QByteArray("HTTP/1.1 200 OK\r\nServer: TDL/0.18\r\nContent-Type: "+type.toLatin1()+"\r\n\r\n"));
            emit message("HTTP/1.1 200 OK\r\nServer: TDL/0.18\r\nContent-Type: "+type+"\r\n\r\n");
        }
    }
}
